﻿using System;

namespace Model
{
	public class SingleExpression : Expression
	{


		private string attributName;
		private string compare;
		private Object rightSide;
		private Attribut attribut;

		/**
		 * Erzeugt ein SingleExpression Objekt, dass den Wert eines Attributes in
		 * gegebener Zelle mit dem übergebenen Wert vergleicht.
		 * 
		 * @param zelle
		 *            die Zelle dessen Attribut überprüft wird
		 * @param attributName
		 *            der Name des Attributs das überprüft wird
		 * @param compare
		 *            "<", ">", oder "=" sind hier erlaubt
		 * @param rightSide
		 *            der Wert mit dem verglichen wird (string oder Double). Dies
		 *            muss mit dem AttributTyp des spezifizierten Attributs
		 *            übereinstimmen.
		 * @throws Exception 
		 */
		public SingleExpression(string attributName, string compare,
				Object rightSide)
		{
			// Check richtige Belegung der Expression
			if (!compare.Equals("<") || !compare.Equals(">")
					|| !compare.Equals("="))
			{
				if (!(rightSide is string)
						|| !(rightSide is Double)
						|| !(rightSide is int))
				{

					this.attributName = attributName;
					this.compare = compare;
					this.rightSide = rightSide;


				}
				else
					throw new Exception("Falscher Parametertyp in rightSide: " + rightSide);
			}
			else
				throw new Exception(compare + " ist kein gültiger Vergleichsoperator.");

		}

		public override bool evaluate(Cell cellToEval)
		{
			if (!cellToEval.Attributes.ContainsKey(attributName))
			{
				if (Environment.CellDefinitions.ContainsKey(attributName))
				{

					return Environment.evaluateExpression(cellToEval, attributName, compare, rightSide);
				}

				throw new Exception("Attributname: " + attributName + " ist weder Attributname, noch CellDefinition");
			}
			else
			{

				this.cellEvaluate = cellToEval;
				if (cellEvaluate.Attributes[attributName] != null)
				{
					if (cellDefinition.Attributes[attributName] is StringAttribut && compare != "=")
						throw new Exception("stringAttribut kann nicht über " + compare + " verglichen werden!");
					else
					{
						this.attribut = cellDefinition.Attributes[attributName];

					}
				}
				else
					throw new Exception("Ungültiger Attributname: " + attributName + " für " + cellDefinition);

				if (cellDefinition == null || attribut == null || attributName == null || compare == null || rightSide == null || cellEvaluate == null)
				{
					throw new NullReferenceException("Mindestens ein Wert ist null: \n" + this.ToString());
				}
				if (attribut is NumberAttribut)
				{
					attribut = cellEvaluate.Attributes[attributName];
					double compValue = 0;
					if (rightSide is int)
						compValue = ((double)(int)rightSide);
					else
					{
						if (rightSide is string)
							compValue = Double.Parse((string)rightSide);
						else
							compValue = (double)rightSide;
					}
					switch (compare)
					{
						case "<":
							return ((NumberAttribut)attribut) < compValue;
						case ">":
							return ((NumberAttribut)attribut) > compValue;
						case "=":
							return ((NumberAttribut)attribut) == compValue;
						default:
							throw new Exception("Evaluation lief falsch.");

					}
				}
				else
				{
					attribut = cellEvaluate.Attributes[attributName];
					return ((StringAttribut)attribut).Equals(rightSide);
				}
			}
		}

		public override string ToString()
		{
			string message =
					"Zelle = " + cellDefinition + "\n," +
					"Attribut = " + attribut + "\n," +
					"AttributName = " + attributName + "\n," +
					"Vergleichsoperator = " + compare + "\n," +
					"Vergleichswert = " + rightSide + "\n";
			return message;
		}
	}
}
